package com.zhb.cloud.hystrix.command;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.zhb.cloud.core.JsonReturn;

/**
 * @ClassName: HystrixCircuitBreaker
 * @author: zhb
 * @date: 2017年8月8日 下午2:53:52
 * @Description: 熔断实现
 */
public class CustomerHystrixCommand111 extends HystrixCommand<String> {
    Logger logger = LoggerFactory.getLogger(CustomerHystrixCommand111.class);
    private static final int DEFAULT_THREADPOOL_CORE_SIZE = 10;
    public final String userName;

    /**
     * 断路器配置未来可优化为动态配置，策略不写死在代码中
     */
    public CustomerHystrixCommand111(String userName) {
        // 用Dubbo服务提供者接口名来定义断路器分组key
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("consumer"))
                // 用Dubbo服务提供者接口的方法名+方法入参个数定义相同依赖的key
                .andCommandKey(HystrixCommandKey.Factory.asKey("test"))
                // 重写断路器基本策略属性
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        // 断路器是否开启，默认：true
                        .withCircuitBreakerEnabled(true)
                        // 统计时间滚动窗口，以毫秒为单位，默认：10秒
                        .withMetricsRollingStatisticalWindowInMilliseconds(10000)
                        // 断路器在整个统计时间内是否开启的阀值，也就是10秒钟内至少请求10次，断路器才发挥起作用
                        .withCircuitBreakerRequestVolumeThreshold(10)
                        // 断路器默认工作时间，默认:5秒，断路器中断请求5秒后会进入半打开状态，放部分流量过去重试
                        .withCircuitBreakerSleepWindowInMilliseconds(5000)
                        // 当出错率超过30%后断路器启动，默认:50%
                        .withCircuitBreakerErrorThresholdPercentage(30)
                        // 是否开启Hystrix超时机制，这里禁用Hystrix的超时，使用dubbo的超时
                        .withExecutionTimeoutEnabled(true).withExecutionTimeoutInMilliseconds(10000))
                // 线程池配置，可考虑获取Dubbo提供者的线程数来配置断路器的线程数，若使用Hystrix的线程数则应大于Dubbo服务提供者的线程数，保证管道匹配
                .andThreadPoolPropertiesDefaults(
                        HystrixThreadPoolProperties.Setter().withCoreSize(DEFAULT_THREADPOOL_CORE_SIZE)));
        this.userName = userName;
    }

    /**
     * 根据需要重写失败回退逻辑（降级逻辑）
     * 
     * @return
     */
    @Override
    protected String getFallback() {
        JsonReturn jsonReturn = new JsonReturn();
        jsonReturn.setCode(100);
        jsonReturn.setData("查询失败");
        jsonReturn.setMessage("太火爆了");
        return JSONObject.toJSONString(jsonReturn);
    }

    @Override
    protected String run() {
        logger.info("Execution of Command: url={}", userName);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String url = "";
        HttpGet httpGet = new HttpGet(url);
        try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
            HttpEntity entity = (HttpEntity) response.getEntity();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
            String total = "";
            String line = bufferedReader.readLine();
            while (line != null) {
                total += line;
                line = bufferedReader.readLine();
            }
            return total;
        } catch (Exception exception) {

        }
        return url;
    }
}
